import { Destroyable, Event, Listener } from "xbsj-base";
import { ESVOption } from "../ESJTypes";
import { ESViewer } from "../ESViewer";
import { SceneObjectsManager } from "./SceneObjectsManager";

export class ViewersManager extends Destroyable {

    private _viewersChanged = this.disposeVar(new Event<[toDels: ESViewer[], toAdds: ESViewer[]]>());
    get viewersChanged() { return this._viewersChanged; }

    private _viewers = new Set<ESViewer>();
    get viewers() { return this._viewers as Readonly<Set<ESViewer>>; }
    getViewers() { return [...this._viewers] as Readonly<ESViewer[]>; }

    private _viewersToChange = this.dv(new Event<[toDels: ESViewer[], toAdds: ESViewer[]]>());
    get viewersToChange() { return this._viewersToChange as Listener<[toDels: ESViewer[], toAdds: ESViewer[]]>; }

    createViewer<T extends ESViewer>(option: ESVOption) {
        const viewer = ESViewer.context.createViewer(option);
        this._viewers.add(viewer);
        this._viewersChanged.emit([], [viewer]);
        return viewer as T;
    }

    destroyViewer<T extends ESViewer>(viewer: T) {
        this._viewers.delete(viewer);
        this._viewersChanged.emit([viewer], []);
    }

    constructor(private _sceneObjectsManager: SceneObjectsManager) {
        super();

        this.d(() => {
            for (const viewer of this._viewers) { viewer.destroy(); }
            this._viewers.clear();
        });

        //初始化创建所有对象
        this.viewers.forEach((viewer) => {
            const objs = this._sceneObjectsManager.sceneObjects;
            viewer.add(...objs);
        })

        //销毁时处理对象
        this.d(() => {
            const objs = this._sceneObjectsManager.sceneObjects;
            this.viewers.forEach((viewer) => { viewer.delete(...objs); })
        })

        //内部对象变化后处理对象
        this.d(this._sceneObjectsManager.sceneObjectsToChange.don((toDels, toAdds) => {
            this.viewers.forEach((viewer) => {
                viewer.add(...toAdds);
                viewer.delete(...toDels);
            })
        }));


        //视口变化后处理对象
        this.d(this.viewersChanged.don((toDelvs, toAddvs) => {
            const objs = this._sceneObjectsManager.sceneObjects;
            toAddvs.forEach((viewer) => { viewer.add(...objs); });
            toDelvs.forEach((viewer) => { viewer.delete(...objs); });
        }));
    }
}
